//------------------------------------------------------------------------
// Abstract: Implement of class XFile
//
// Authoring: XiaoHanxiong
//
// Time: 2014.04.17
//
// Static test:
//
// Version history:
//		Ver_1.0	: 2014.04.17	XiaoHanxiong
//------------------------------------------------------------------------
#include "stdafx.h"
#include "XFile.h"


namespace Library
{
	void SwapEndian( wchar_t& word )
	{
		UINT8* first = (UINT8*)&word;
		UINT8* second = first + 1;
		UINT8 tmp = *first;
		*first = *second;
		*second = tmp;
	}

	void processUnicodeBE( FILE* file, wchar_t* buffer, size_t max_size )
	{
		wchar_t* tmp_ptr = buffer;
		for(size_t n = 0; n < max_size * 2; n++)
			SwapEndian(*(wchar_t*)tmp_ptr++);
		wstring wstr(buffer);
		size_t pos = wstr.find(_T("\n"));
		if(pos != wstring::npos)
		{
			wstr.erase(pos - 1, wstring::npos);
			fseek(file, (pos+2) * sizeof(wchar_t) , SEEK_SET);
			memset(buffer, 0, XFile::Max_Text_size);
			memcpy(buffer, wstr.c_str(), wstr.size() * sizeof(wchar_t));
		}
	}

	XFile::XFile()
		: m_encoding(Unvalid)
		, m_hFile(NULL)
	{

	}

	XFile::~XFile()
	{

	}

	bool XFile::ReNameFile( char* oldName, char* newName ) /*static*/
	{
		return (bool)rename(oldName, newName);
	}

	bool XFile::OpenA( char* fileName, Encoding type, const char* openMode )
	{
		Close();
		fopen_s(&m_hFile, fileName, openMode);
		if(m_hFile)
		{
			m_encoding = ANSI;
			return true;
		}
		return false;
	}

	bool XFile::OpenW( wchar_t* fileName, Encoding type, const wchar_t* openMode )
	{
		wstring open_type(openMode);
		switch(type)
		{
		case UTF8:
			open_type += _T(",ccs=UTF-8");
			break;

		case UnicodeLE:
			open_type += _T(",ccs=UNICODE");
			break;

		case UnicodeBE:
			open_type += _T("b+");
			break;

		default:
			return false;
		}

		Close();
		errno_t code = _wfopen_s(&m_hFile, fileName, open_type.c_str());
		if(!m_hFile) return false;

		if(type == UnicodeBE)
		{
			char buffer[16] = {0};
			fread_s(buffer, 16, 1, 2, m_hFile);
			int word = *(int*)buffer & 0xFFFF;
			if(word != 0xFFFE) return false;
		}

		m_encoding = type;
		return true;
	}

	bool XFile::OpenB( char* fileName, const char* openMode /* ="r+"*/ )
	{
		fclose(m_hFile);
		m_hFile = NULL;
		fopen_s(&m_hFile, fileName, openMode);
		return (m_hFile != NULL);
	}

	void XFile::Close()
	{
		if(m_hFile)
		{
			fclose(m_hFile);
			m_hFile = NULL;
			m_encoding = Unvalid;
		}
	}

	void XFile::ReadLineA( string& str, size_t max_size )
	{
		if(m_encoding == ANSI && max_size <= Max_Text_size && m_hFile)
		{
			char buffer[Max_Text_size] = {0};
			fgets(buffer, max_size, m_hFile);
			str = buffer;
		}
	}

	void XFile::ReadLineA( char* buffer, size_t buffer_size, size_t max_size )
	{
		if( m_encoding == ANSI && max_size <= Max_Text_size && 
			buffer_size >= max_size && m_hFile )
		{
			char tmp_buffer[Max_Text_size] = {0};
			fgets(tmp_buffer, max_size, m_hFile);
			memcpy(buffer, tmp_buffer, max_size);
		}
	}

	void XFile::ReadA( string& str, size_t size )
	{
		if(m_encoding == ANSI && size <= Max_Text_size && m_hFile)
		{
			char tmp_buffer[Max_Text_size] = {0};
			fread_s(tmp_buffer, Max_Text_size, 1, size, m_hFile);
			str = tmp_buffer;
		}
	}

	void XFile::ReadA( char* buffer, size_t buffer_size, size_t size )
	{
		if( m_encoding == ANSI && size <= Max_Text_size && 
			buffer_size >= size && m_hFile )
		{
			char tmp_buffer[Max_Text_size] = {0};
			fread_s(tmp_buffer, Max_Text_size, 1, size, m_hFile);
			memcpy(buffer, tmp_buffer, size);
		}
	}

	void XFile::ReadLineW( wstring& str, size_t max_size )
	{
		if( (m_encoding == UTF8 || m_encoding == UnicodeBE || m_encoding == UnicodeLE) &&
			max_size < Max_Text_size && m_hFile )
		{
			wchar_t buffer[Max_Text_size] = {0};
			fgetws(buffer, max_size, m_hFile);
			if(m_encoding == UnicodeBE)
			{
				processUnicodeBE(m_hFile, buffer, max_size);
			}
			str = buffer;
		}
	}

	void XFile::ReadLineW( wchar_t* buffer, size_t buffer_size, size_t max_size )
	{
		if( (m_encoding == UTF8 || m_encoding == UnicodeBE || m_encoding == UnicodeLE) &&
			max_size < Max_Text_size && buffer_size >= max_size && m_hFile)
		{
			wchar_t tmp_buffer[Max_Text_size] = {0};
			fgetws(tmp_buffer, max_size, m_hFile);
			if(m_encoding == UnicodeBE)
			{
				processUnicodeBE(m_hFile, tmp_buffer, max_size);
			}
			memcpy(buffer, tmp_buffer, (max_size) * sizeof(wchar_t));
		}
	}

	void XFile::ReadW( wstring& str, size_t size )
	{
		if( (m_encoding == UTF8 || m_encoding == UnicodeBE || 
			m_encoding == UnicodeLE) && m_hFile)
		{
			wchar_t buffer[Max_Text_size] = {0};
			fread_s(buffer, Max_Text_size, size, 1, m_hFile);
			if(m_encoding == UnicodeBE)
			{
				wchar_t* ptr = buffer;
				for(size_t n = 0; n < size; n++)
					SwapEndian(*(wchar_t*)ptr++);
			}
			str = buffer;
		}
	}

	void XFile::ReadW( wchar_t* buffer, size_t buffer_size, size_t size )
	{
		if( (m_encoding == UTF8 || m_encoding == UnicodeBE || m_encoding == UnicodeLE) &&
			buffer_size >= size && m_hFile)
		{
			wchar_t tmp_buffer[Max_Text_size] = {0};
			fread_s(tmp_buffer, Max_Text_size, size, 1, m_hFile);
			if(m_encoding == UnicodeBE)
			{
				wchar_t* ptr = tmp_buffer;
				for(size_t n = 0; n < size; n++)
					SwapEndian(*(wchar_t*)ptr++);
			}
			memcpy(buffer, tmp_buffer, size);
		}	
	}

	//////////////////////////////////////////////////////////////////////////
	void XFile::WriteA( string& str )
	{
		if(m_encoding == ANSI && m_hFile)
		{
			fprintf_s(m_hFile, "%s", str.c_str());
		}
	}

	void XFile::WriteA( char* buffer, size_t size )
	{
		if(m_encoding == ANSI && m_hFile)
		{
			fwrite(buffer, 1, size, m_hFile);
		}
	}

	void XFile::WriteLineA( string& str )
	{
		if(m_encoding == ANSI && m_hFile)
		{
			fprintf_s(m_hFile, "%s\n", str.c_str());
		}
	}

	void XFile::WriteLineA( char* buffer, size_t size )
	{
		if(m_encoding == ANSI && m_hFile)
		{
			string str(buffer);
			fprintf_s(m_hFile, "%s\n", str.c_str());
		}
	}

	void XFile::WriteW( wstring& str )
	{
		if( (m_encoding == UTF8 || m_encoding == UnicodeBE ||
			m_encoding == UnicodeLE) && m_hFile)
		{
			fwprintf_s(m_hFile, _T("%s"), str.c_str());
		}
	}

	void XFile::WriteW( wchar_t* buffer, size_t size )
	{
		if( (m_encoding == UTF8 || m_encoding == UnicodeBE ||
			m_encoding == UnicodeLE) && m_hFile)
		{
			fwrite(buffer, 1, size, m_hFile);
		}
	}

	void XFile::WriteLineW( wstring& str )
	{
		if( (m_encoding == UTF8 || m_encoding == UnicodeBE ||
			m_encoding == UnicodeLE) && m_hFile)
		{
			fwprintf_s(m_hFile, _T("%s\n"), str.c_str());
		}
	}

	void XFile::WriteLineW( wchar_t* buffer, size_t size )
	{
		if( (m_encoding == UTF8 || m_encoding == UnicodeBE ||
			m_encoding == UnicodeLE) && m_hFile)
		{
			wstring wstr(buffer);
			fwprintf_s(m_hFile, _T("%s\n"), wstr.c_str());
		}
	}

	void XFile::Flush()
	{
		if(m_hFile)
		{
			fflush(m_hFile);
		}
	}

	bool XFile::Seek( size_t pos )
	{
		if(m_hFile)
		{
			if(m_encoding != UnicodeBE) fseek(m_hFile, pos, SEEK_SET);
			else fseek(m_hFile, pos + 2, SEEK_SET);
			return true;
		}
		return false;
	}

	UINT32 XFile::GetPosition()
	{
		UINT32 pos = 0;
		if(m_hFile)
		{
			if(m_encoding != UnicodeBE) pos = ftell(m_hFile);
			else pos = ftell(m_hFile) - 2;
		}
		return pos;
	}

	UINT32 XFile::GetLength()
	{
		UINT32 pos = 0;
		if(m_hFile)
		{
			fseek(m_hFile, 0, SEEK_END);
			if(m_encoding != UnicodeBE) pos = ftell(m_hFile);
			else pos = ftell(m_hFile) - 2;
		}
		return pos;
	}

	Library::Encoding XFile::GetEncoding()
	{
		return(m_encoding);
	}

	bool XFile::IsOpen()
	{
		return (m_hFile != NULL);
	}

	bool XFile::IsEof()
	{
		return feof(m_hFile);
	}

	void XFile::ReadB( void* buffer, size_t bufferSize, size_t rSize )
	{
		if(m_hFile)
		{
			fread_s(buffer, bufferSize, 1, rSize, m_hFile);
		}
	}

	void XFile::WriteB( void* src, size_t srcSize )
	{
		if(m_hFile)
		{
			fwrite(src, 1, srcSize, m_hFile);
		}
	}
}